package com.vanke.devops.domain.manager.docker.impl;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.ListContainersCmd;
import com.github.dockerjava.api.model.Container;
import com.github.dockerjava.api.model.Info;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.jaxrs.JerseyDockerCmdExecFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.vanke.core.util.JsonUtil;
import com.vanke.core.util.StringUtil;
import com.vanke.devops.dal.model.Endpoints;
import com.vanke.devops.domain.domain.endpoints.IEndpointsService;
import com.vanke.devops.domain.job.ContainerMonitorJob;
import com.vanke.devops.domain.manager.docker.DockerConstants;
import com.vanke.devops.domain.manager.docker.DockerManager;
import com.vanke.devops.domain.manager.docker.extend.DockerClientExtend;
import com.vanke.devops.domain.manager.docker.extend.command.ListServicesCmd;
import com.vanke.devops.domain.manager.docker.extend.impl.DockerClientExtendImpl;
import com.vanke.devops.domain.manager.docker.extend.impl.DockerCmdExecFactoryExtendImpl;
import com.vanke.devops.domain.manager.docker.extend.model.Node;
import com.vanke.devops.domain.manager.docker.extend.model.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;

/**
 * @author 陈景阳
 * @since 2018/4/1
 */
@Service
public class DockerManagerImpl implements DockerManager {

    private static final Logger LOGGER = LoggerFactory.getLogger(DockerManagerImpl.class);

    private static final Map<String,DockerClientExtend> CLIENTS = Maps.newConcurrentMap();

    @Autowired
    private IEndpointsService endpointsService;

    @Autowired
    private ContainerMonitorJob containerMonitorJob;

    @PostConstruct
    public void init(){

        CLIENTS.clear();

        List<Endpoints> list =  endpointsService.getAll();

        list.forEach( endpoints -> {
            DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
                    .withDockerHost(DockerConstants.TCP_PREFIX + endpoints.getIp()
                            + ":" + DockerConstants.DOCKER_API_PORT)
                    .withRegistryUrl(DockerConstants.HARBOR_URL)
                    .withRegistryUsername(DockerConstants.HARBOR_USERNAME)
                    .withRegistryPassword(DockerConstants.HARBOR_PASSWORD)
                    .build();

            DockerCmdExecFactoryExtendImpl factoryExtend = new DockerCmdExecFactoryExtendImpl();
            DockerClient client = DockerClientBuilder
                    .getInstance(config)
                    .withDockerCmdExecFactory(factoryExtend)
                    .build();
            CLIENTS.put(endpoints.getIp(),new DockerClientExtendImpl(factoryExtend,client));
        });

    }

    @Override
    public List<Container> ps(String ip){
        DockerClient client = CLIENTS.get(ip).getDockerClient();
        if(client == null){
            return Lists.newArrayList();
        }
        ListContainersCmd cmd = client.listContainersCmd();
        return cmd.exec();
    }

    @Override
    public void  stats(String ip){
        DockerClient client = CLIENTS.get(ip).getDockerClient();
        List<Container> containers = ps(ip);
        containers.forEach( container -> {
            ResultCallbackStatisticsImpl resultCallbackStatistics =
                    new ResultCallbackStatisticsImpl(containerMonitorJob,container,ip);
            client.statsCmd(container.getId()).exec(resultCallbackStatistics);
        });
    }

    @Override
    public List<com.vanke.devops.domain.manager.docker.extend.model.Service> services(String ip) {
        return this.withNameServices(ip,null);
    }

    @Override
    public com.vanke.devops.domain.manager.docker.extend.model.Service service(String ip, String id) {
        return CLIENTS.get(ip)
                .inspectServiceCmd()
                .withServiceId(id)
                .exec();
    }

    @Override
    public List<com.vanke.devops.domain.manager.docker.extend.model.Service> withNameServices(String ip, String name) {
        DockerClientExtend client = CLIENTS.get(ip);
        if(client != null){
            ListServicesCmd cmd = client.listServicesCmd();
            if(StringUtil.isNotEmpty(name)){
                cmd.withName(name);
            }
            return cmd.exec();
        }
        return Lists.newArrayList();

    }

    @Override
    public List<Task> withServiceNameTasks(String ip, String serviceName) {
        DockerClientExtend client = CLIENTS.get(ip);
        return client.listTasksCmd().withServiceName(serviceName).exec();
    }

    @Override
    public List<Node> nodes(String ip) {
        DockerClientExtend client = CLIENTS.get(ip);
        return client.listNodesCmd().exec();
    }

    @Override
    public Info info(String ip) {
        return CLIENTS.get(ip).getDockerClient().infoCmd().exec();
    }
}
